home *** CD-ROM | disk | FTP | other *** search
- /* VMMGR/CCC
- * virtual memory tables and RAM management routines
- *
- * Copyright 1983, 1984 by Jim Kyle - All Rights Reserved
- * Licensed for individual non-commercial use only.
- *
- * created: November 16, 1983 - Jim Kyle
- * changed: November 26, 1983 - Jim Kyle
- * last changed: March 3, 1984 - Jim Kyle
- */
-
- /* data global to this module:
- * first three arrays serve as a structure:
- * struct vmtable {
- * int Secno;
- * char *Slot;
- * int Lru;
- * } Vmtbl[NSLOTS];
- */
- int Secno[NSLOTS]; /* Sector Nbr for slot */
- char *Slot[NSLOTS]; /* Buffer address for slot */
- int Lru[NSLOTS]; /* Usage Counter for slot */
-
- int Cslot; /* Current Slot's index */
- int Frstfs; /* First Free Slot index */
- FILE *Tmpfp; /* fp for VM temp file */
- static int Free; /* Head of diskfile ASL */
- int Lstsec; /* Last Sector Nbr used */
- int *Bcptr; /* Ptr to curr Byte Count */
- int *Nxptr; /* Ptr to Next link, curr */
- int Curr; /* Current-block number */
-
- int *Pvptr; /* Ptr to Prev link, curr */
- int *Lcptr; /* Ptr to curr Line ctr */
- char *Dbptr; /* Ptr to curr Data base */
- int Dbndx; /* Relative to Dbptr */
- int Flcb; /* First line curr block */
- int Llcb; /* Last line current block */
- int Cur_ln; /* Current line's number */
- int Lltf; /* Last line total file */
- char Bfrs[BFRSZ]; /* The slots themselves */
- #option ZVAR ON
- int Iflag; /* 0 until tempfile created */
- #option ZVAR OFF
-
- /*
- * vm_init() must be called before any use of the VM
- * routines, to properly initialize all tables, counts,
- * and pointers.
- *
- * It will return OK if successful, or ERR if not.
- */
- vm_init() /* initialize the tables */
- { int i;
- char *j;
- j = Bfrs;
- for (i=0; i < NSLOTS; ++i) {
- Slot[i] = j; /* set in addresses */
- Lru[i] = Secno[i] = *(j+1) = *j = 0;
- j += BLKSIZ;
- }
- if (Iflag == 0)
- Tmpfp = fopen("VM/TMP","w"); /* create tempfile */
- Iflag = EOF; /* set Iflag */
- /* zero out counters and pointers */
- Flcb = Llcb = Lltf = Frstfs = Free = Dbndx = 0;
- Lstsec = SECBEG; /* no sectors used yet */
- /* changed from vm_get(0) on 3-3-84 - jk */
- return(go_top()); /* start sec 0, slot 0 */
- }
-
- /*
- * vm_get() makes the block identified by its single
- * argument the "current block" and sets all pointers
- * accordingly. Paging to-from disk file is automatic.
- *
- * Return value is OK if successful, else ERR.
- */
- vm_get(sec) int sec; /* make 'sec' Current block */
- { Cslot = findslot(sec); /* get it into RAM */
- if (Cslot < 0)
- return(ERR);
- Bcptr = Slot[Cslot]; /* ptr to curr byte count */
- Curr = sec; /* identify current block */
- Nxptr = Bcptr + 1; /* ptr to next block */
- Pvptr = Nxptr + 1; /* ptr to prev block */
- Lcptr = Pvptr + 1; /* ptr to line count */
- Dbptr = Lcptr + 1; /* base of data area */
- return(OK);
- }
-
- /*
- * findslot() gets the referenced block into one of the
- * RAM slots, swapping in or out as required.
- *
- * Return value is the slot number if successful, or
- * ERR if any error occurs.
- */
- findslot(sec) int sec; /* returns slotndx or ERR */
- { int i,j,k;
- for (i=0; i<Frstfs; ++i) /* bump usage count */
- ++Lru[i];
- for (i=0; i<Frstfs; ++i) /* already here? */
- if (sec == Secno[i]) {
- Lru[i] = 0; /* yes, clear LRU */
- return(i); /* and get out */
- }
- if (Frstfs < NSLOTS) /* no, is one free? */
- k = Frstfs++; /* yes, take it */
- else { /* no, free one */
- j = *Lru;
- k = 0;
- for (i=1; i<NSLOTS; ++i)
- if (j < Lru[i]) { /* find oldest */
- j = Lru[i];
- k = i;
- }
- if (free_slot(k,Secno[k]))
- return(vm_err("free_slot write"));
- }
- return(fill_slot(k,sec)==OK ? k : ERR);
- }
-
- /*
- * free_slot() moves the referenced slot's contents to
- * the referenced block on disk. It is called only by
- * findslot().
- */
- free_slot(slt,sec) int slt,sec; /* move to disk */
- { int i,j,*k;
- k = Slot[slt]; /* ptr to buffer space */
- if (*k & DIRTY)
- *k &= CLEAN; /* clean up before writing */
- else
- return(OK); /* no need to write out */
- /* seek to sec */
- if (sec_seek(Tmpfp,sec))
- return(vm_err("free_slot seek"));
- /* write BLKSIZ bytes from Slot buffer */
- return((fwrite(Tmpfp,k,BLKSIZ)==BLKSIZ) ? OK : ERR);
- }
-
- /*
- * fill_slot() moves the content of the referenced block
- * into the referenced slot. It is called only by
- * findslot().
- */
- fill_slot(slt,sec) int slt,sec; /* move fm disk */
- { int i,j,*k;
- k = Slot[slt]; /* ptr to buffer space */
- Secno[slt] = sec; /* identify the sector */
- Lru[slt] = 0; /* clear usage counter */
- if (sec > Lstsec) { /* extending disk, no read */
- Lstsec = sec;
- *k++ = BHAD; /* initial byte count */
- for (i=1; i++ < 512;)
- *k++ = 0; /* zero rest of slot */
- return(OK);
- }
- /* must seek to sec */
- if (sec_seek(Tmpfp,sec))
- return(vm_err("fill_slot seek"));
- /* then read BLKSIZ bytes to Slot buffer */
- i = fread(Tmpfp,k,BLKSIZ);
- if (i < 1)
- return (i ? ERR : EOF);
- return(OK);
- }
-
- /*
- * add_blk() inserts an empty new block into the work
- * file chain immediately after the current block. The
- * current block remains current. Normal return value
- * is OK; return of ERR indicates hopeless confusion in
- * VM file and abort of the run should result.
- *
- * Note that there is no special treatment for the last
- * block of the file. Block 0 is both the first and the
- * last block; the file is "ring-linked". This makes it
- * easy to reach the end of file by getting Block 0 and
- * then getting its "prev" block. This is the major
- * difference between this VM system and that used in
- * Ed Ream's "RED".
- */
- add_blk() /* links new block after Curr one */
- /* returns OK or ERR only */
- { int new,cur,nxt; /* link values */
- /* save links */
- cur = Curr;
- nxt = *Nxptr;
- if (Free) { /* free list not empty */
- if (vm_get(Free)) return(vm_err("add_blk free"));
- new = Free;
- Free = *Nxptr; /* cut it loose */
- smudge();
- }
- else /* must create new one */
- new = Lstsec + BLKINC;
- /* patch all the pointers */
- if (vm_get(nxt)) return(vm_err("add_blk nxt"));
- *Pvptr = new;
- smudge();
- /* now set up the new one. it will be created by the
- * the vm_get() call, if it did not already exist.
- */
- if (vm_get(new)) return(vm_err("add_blk new"));
- *Nxptr = nxt;
- *Pvptr = cur;
- *Bcptr = BHAD;
- *Lcptr = 0;
- smudge();
- if (vm_get(cur)) return(vm_err("add_blk cur"));
- *Nxptr = new;
- smudge();
- return (OK);
- }
-
- /*
- * rel_blk() deletes the current block from the work
- * file chain and adds it to the head of the free list.
- * The block PRECEDING the current block becomes the
- * current one. Normal return value is OK; if you try
- * to release Block 0 the return value will be EOF. A
- * return value of ERR indicates the function failed to
- * complete successfully; the run should abort in this
- * case as the VM file is hopelessly confused!
- */
- rel_blk()
- { int rel,prv,nxt; /* links */
- if (Curr) { /* never release Block 0! */
- /* save link values */
- rel = Curr;
- prv = *Pvptr;
- nxt = *Nxptr;
- /* fix backward link first */
- if (vm_get(nxt)) return(vm_err("rel_blk next"));
- *Pvptr = prv;
- smudge();
- /* then take out of chain */
- if (vm_get(prv)) return(vm_err("rel_blk prev"));
- *Nxptr = nxt;
- smudge();
- /* and put on free list */
- if (vm_get(rel)) return(vm_err("rel_blk curr"));
- *Nxptr = Free;
- *Pvptr = ERR; /* for debugging */
- smudge();
- Free = rel; /* point Free to this one */
- return(vm_get(prv));
- }
- else return(EOF);
- }
-
-